using System.Collections.Generic;
using System.Web.Mvc;
using System.Web;
using System.Web.Security;
using System.Linq;
using System.IO;
using System;
using System.Threading;

using WikiPlex;
using WikiPlex.Formatting;

using Microsoft.Practices.ServiceLocation;

using MvcCms.Service.Code.Wiki;
using MvcCms.Data;
using MvcCms.Service.Cache;
using MvcCms.Service;
using MvcCms.Service.Code.Membership;
using MvcCms.Web.ViewModels;
using MvcCms.Service.Helpers;
using MvcCms.Service.Logging;
using MvcCms.Service.Filters;
using MvcCms.Service.Code;

namespace MvcCms.Web.Controllers
{
    [HandleError]
    public class HomeController : Service.Code.BaseClasses.CMSControllerBase
    {
        #region Constructors
        private readonly ICmsService _cmsService;
        private readonly IZoneService _zoneService;
        private readonly ICacheService _cacheService;
        private Portal _currentPortal;
        private readonly IPortalService _portalService;
        private readonly IAccountService _accountService;
        private readonly IFormsAuthentication _formsAuth;
        public HomeController(IZoneService zoneService, ICmsService cmsService, IFormsAuthentication formsAuth, ICacheService cacheService, IPortalService portalService, IAccountService accountService)
            : base(cmsService, zoneService, accountService)
        {
            _formsAuth = formsAuth;
            _zoneService = zoneService;
            _cmsService = cmsService;
            _portalService = portalService;
            _cacheService = cacheService;
            _accountService = accountService;
            _currentPortal = cacheService.GetCurrentPortal();
        }        
        #endregion

        [CleanUrls]
        //[RedirectToNonSslIfNotAuthenticated(Redirect = true)]
        //[RequireSslIfIsAuthenticated(Redirect = true)]
        public ActionResult Index(string path, int? parentPageId, string languagePathId)
        {
            try
            {
                if (Request.Browser.IsMobileDevice)
                {
                    //return new PermanentRedirectResult("your mobile app");
                }

                string pageTitle = "";
                ContentPage contentPage;
                var fullPath = Request.Url.AbsolutePath.ToLower();

                var isRedirect = false;
                var redirKey = "__Make301Redir_" + Thread.CurrentContext.ContextID.ToString();
                var redirThreadData = Thread.GetNamedDataSlot(redirKey);
                if (redirThreadData != null)
                {
                    var doRedirect = Thread.GetData(redirThreadData);
                    if (doRedirect != null) { isRedirect = (bool)doRedirect; }
                }
                if (isRedirect)
                {
                    return Make301Redir(fullPath, false);
                }
                Thread.FreeNamedDataSlot(redirKey);

                ViewData["SiteName"] = _currentPortal.DisplayName;
                ViewData["SiteURL"] = _currentPortal.URLAuthority;
                ViewData["DefaultLangID"] = _currentPortal.DefaultLanguage.LanguageID;

                contentPage = _cmsService.GetContentPageForRequest();

                if (contentPage == null)
                {
                    return Make301Redir(fullPath, false);
                }
                Thread.FreeNamedDataSlot(redirKey);

                var key = "__RequestedPage_" + Thread.CurrentContext.ContextID.ToString();
                Thread.FreeNamedDataSlot(key);
                key = "__PageTitle_" + Thread.CurrentContext.ContextID.ToString();
                var pageTitleThreadData = Thread.GetNamedDataSlot(key);
                pageTitle = Thread.GetData(pageTitleThreadData).ToString();
                Thread.FreeNamedDataSlot(key);

                //ok we have the correct page now
                //lets see if there are any restrictions
                if ((contentPage.OnlyForMembers || contentPage.ContentCategory.OnlyForMembers) && !Roles.IsUserInRole("Admin"))
                {
                    if (string.IsNullOrEmpty(contentPage.ContentCategory.OnlyForMembersRoles))
                    {
                        if (!Roles.IsUserInRole("User"))
                        {
                            return RedirectToAction("MembersOnly");
                        }
                    }
                    else
                    {
                        var isAllowed = false;
                        foreach (var role in contentPage.ContentCategory.OnlyForMembersRoles.Split(',').ToList())
                        {
                            if (Roles.IsUserInRole(role))
                            {
                                isAllowed = true;
                            }
                        }
                        if (!isAllowed) { return RedirectToAction("MembersOnly"); }
                    }
                }
                if (contentPage.ContentCategory.RequireSSL)
                {
                    if (Request.Url.Host.ToString() != "localhost")
                    {
                        if (!Request.IsSecureConnection)
                        {
                            //make a 301 for this
                            return Make301Redir(fullPath, true);
                        }
                    }
                }
                //apply the widgets
                string[] roles = new string[0];
                var user = _accountService.GetUser();
                if (user != null)
                {
                    roles = Roles.GetRolesForUser();
                }

                //get widgets that are not weighted for the page
                var widgets = _cmsService.ListWidgetsForPage(contentPage.ContentPageID);
                foreach (var widget in widgets.Where(w => w.IsForWeightedContent.Equals(false)))
                {
                    contentPage.Body = contentPage.Body.Replace("<div id=\"" + widget.TargetDiv + "\"></div>", "<div id=\"" + widget.TargetDiv + "\">" + widget.HTML + "</div>");
                }

                //get weighted content widget's declared on the page
                if (!string.IsNullOrEmpty(contentPage.TargetDivsForWeightedContent))
                {
                    var divsToLoadWithContent = contentPage.TargetDivsForWeightedContent.Split(',');
                    for (int i = 0; i < divsToLoadWithContent.Length; i++)
                    {
                        var widgetToLoad = _cmsService.GetNextWeightedWidgetForTargetDiv(divsToLoadWithContent[i], Request.IsAuthenticated, roles);
                        if (widgetToLoad != null)
                        {
                            contentPage.Body = contentPage.Body.Replace("<div class=\"" + widgetToLoad.WeightedContent.ContainerClasses + "\" id=\"" + widgetToLoad.WeightedContent.TargetDiv + "\"></div>", "<div class=\"" + widgetToLoad.WeightedContent.ContainerClasses + "\" id=\"" + widgetToLoad.WeightedContent.TargetDiv + "\">" + widgetToLoad.Widget.HTML + "</div>");
                        }
                    }
                }
                //lets get weightedcontentmodules, these will have ajax rotation bound to the target div
                var weightedContentModules = _cmsService.ListWeightedContents().Where(w => w.IsModuleType).ToList();

                //get the alt language versions
                var altLanguageVersions = _cmsService.ListAltLanguagePages(contentPage.ContentPageID);
                if (_currentPortal.UsesWikiForCMS || contentPage.UseWikiMarkup && contentPage.ContentCategory.Path != "site-search")
                {
                    var wikiEngine = ServiceLocator.Current.GetInstance<IWikiEngine>();
                    ViewData["PageContent"] = wikiEngine.Render(contentPage.Body, GetFormatter());
                }
                else
                {
                    ViewData["PageContent"] = contentPage.Body;
                }

                if (contentPage.ShowContributorLink)
                {
                    contentPage = _cmsService.GetContentPage(contentPage.ContentPageID);
                }

                var model = new HomeModel
                {
                    _WeightedContentsModuleType = weightedContentModules,
                    _CurrentPortal = _currentPortal,
                    _ContentPage = contentPage,
                    _AltLangueVersions = altLanguageVersions
                };

                if (Request.IsAuthenticated)
                {
                    if (user.UserName == "onlineregistration")
                    {
                        _formsAuth.SignOut();
                        user = null;
                    }
                    if (user != null)
                    {
                        ViewData["userguid"] = user.UserID.ToString();
                    }
                    else
                    {
                        ViewData["userguid"] = "";
                    }
                }
                else
                {
                    ViewData["userguid"] = "";
                }
                //comment the lines below if you DON'T have iis7 or are NOT using openauth
                if (Request.Url.Host.ToString() != "localhost")
                {
                    Response.Headers.Add("X-XRDS-Location:", "http://" + _currentPortal.URLAuthority + "/xrds.aspx");
                }
                ViewBag.Title = _currentPortal.DisplayName + " - " + pageTitle;
                ViewData["PageTitle"] = pageTitle;
                return View(model);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(ex.Message, ex);
                return RedirectToAction("error");
            }
        }

        [Authorize]
        public ActionResult PreviewUnPublished(int contentPageId)
        {
            _currentPortal = _cacheService.GetCurrentPortal();

            ViewData["SiteName"] = _currentPortal.DisplayName;
            ViewData["SiteURL"] = _currentPortal.URLAuthority;
            ViewData["DefaultLangID"] = _currentPortal.DefaultLanguage.LanguageID;

            var altLanguageVersions = _cmsService.ListAltLanguagePages(0);
            var weightedContentModules = _cmsService.ListWeightedContents().Where(w => w.WeightedContentID == 0).ToList();

            var contentPageToPreview = _cmsService.GetContentPage(contentPageId);
            ViewData["PageContent"] = contentPageToPreview.Body;
            var model = new HomeModel
            {
                _WeightedContentsModuleType = weightedContentModules,
                _AltLangueVersions = altLanguageVersions,
                _CurrentPortal = _currentPortal,
                _ContentPage = contentPageToPreview
            };

            return View("Index", model);
        }

        private PermanentRedirectResult Make301Redir(string fullPath, bool isSecure)
        {
            //do we have a 301 redirect?
            var oldUrlProtocol = "http://";
            var newUrlProtocol = "http://";
            if (Request.IsSecureConnection) { oldUrlProtocol = "https://"; }
            if (isSecure) { newUrlProtocol = "https://"; }

            var redirect = _cmsService.GetRedirect(oldUrlProtocol + _currentPortal.URLAuthority + fullPath);
            if (redirect != null)
            {
                return new PermanentRedirectResult(redirect.NewPage);
            }
            else
            {
                //let's make one and for now send it to the not found page
                redirect = new Redirect
                {
                    Description = "Auto Generated By MvcCms",
                    NewPage = newUrlProtocol + _currentPortal.URLAuthority + "/notfound",
                    OldPage = oldUrlProtocol + _currentPortal.URLAuthority + fullPath
                };
                _cmsService.CreateRedirect(redirect);
                return new PermanentRedirectResult(this.ControllerContext.RequestContext, "NotFound", "Home");
            }
        }

        [CleanUrls]
        public ActionResult NotFound()
        {
            return View();
        }
        public ActionResult MembersOnly()
        {
            return View();
        }
        public ActionResult SSLRequired()
        {
            return View();
        }
        public ActionResult Error()
        {
            return View();
        }

        [Authorize(Roles = "Editor")]
        public ActionResult EditComment(int id, string routeval)
        {
            ContentComment contentcomment = _cmsService.GetContentComment(id);

            ViewData["PageTitle"] = "Edit Comment";
            return View("EditComment", "DontUseMaster", contentcomment);
        }

        [Authorize(Roles = "User")]
        public ActionResult CommentReply(int id, string routeval)
        {
            ContentComment contentcomment = _cmsService.GetContentComment(id);
            contentcomment.AddedByAnonName = _accountService.GetUser().UserName;

            ViewData["PageTitle"] = "Reply To Comment";
            return View("CommentReply", "DontUseMaster", contentcomment);
        }

        private MacroFormatter GetFormatter()
        {
            var siteRenderers = new IRenderer[]
            {
                new TitleLinkRenderer(Url),
                new TextColorRenderer() ,
                new TextSizeRenderer(),
                new AnyStyleRenderer()
            };
            IEnumerable<IRenderer> allRenderers = Renderers.All.Union(siteRenderers);
            return new MacroFormatter(allRenderers);
        }

    }
}